﻿using NetworkCommsDotNet;
using NetworkCommsDotNet.Connections;
using NetworkCommsDotNet.Connections.TCP;
using NetworkCommsDotNet.DPSBase;
using System;
using System.Collections.Generic;
using System.Net;

namespace NetWorkTcpLibrary
{
    public class NetWorkTcpServer
    {
        #region 托管服务端

        /// <summary>
        /// 在线连接数变化事件
        /// </summary>
        public event Action<int> EventChangeOnlineCount;

        /// <summary>
        /// 需要回执的接收消息的处理事件(对象)
        /// </summary>
        public event Action<Connection, XYZ> ReturnMessgeObjHandle;

        /// <summary>
        /// 消息的处理事件(对象)
        /// </summary>
        public event Action<Connection, XYZ> MessgeObjHandle;

        /// <summary>
        /// 需要回执的接收消息的处理事件(字符串)
        /// </summary>
        public event Action<Connection, string> ReturnMessgeStrHandle;

        /// <summary>
        /// 消息的处理事件(字符串)
        /// </summary>
        public event Action<Connection, string> MessgeStrHandle;

        /// <summary>
        /// 需要返回的消息名称，需要与客户端一致(对象)
        /// </summary>
        public string ReturnObjName = string.Empty;

        /// <summary>
        /// 收到的消息名称(对象)
        /// </summary>
        public string ReceiveObjName = string.Empty;

        /// <summary>
        /// 需要返回的消息名称，需要与客户端一致字符串)
        /// </summary>
        public string ReturnStrName = string.Empty;

        /// <summary>
        /// 收到的消息名称(字符串)
        /// </summary>
        public string ReceiveStrName = string.Empty;

        /// <summary>
        /// 上线事件
        /// </summary>
        public event Action<ConnectionInfo> EventOnLine;

        /// <summary>
        /// 下线事件
        /// </summary>
        public event Action<ConnectionInfo> EventOffLine;

        /// <summary>
        /// 更新线程数线程锁辅助对象
        /// </summary>
        private static object LockOnline = new Object();

        private int connOnlineCount = 0;

        /// <summary>
        /// 在线连接数
        /// </summary>
        private int ConnOnlineCount
        {
            get { return connOnlineCount; }
            set
            {
                //lock (LockOnline)
                //{
                    if (value >= 0)
                    {
                        connOnlineCount = value;
                        EventChangeOnlineCount?.Invoke(connOnlineCount);
                    }
                    else
                    {
                        connOnlineCount = 0;
                        EventChangeOnlineCount?.Invoke(0);
                    }
                //}
            }
        }

        /// <summary>
        /// 服务端监听listener
        /// </summary>
        private TCPConnectionListener listener;

        /// <summary>
        /// 初始化监听类库（每填一个就需要增加一个对应的消息处理事件）
        /// </summary>
        /// <param name="_ReceiveObjName">收到的消息的名称(对象)</param>
        /// <param name="_ReturnName">返回的消息的名称(对象)</param>
        /// <param name="_ReceiveStrName">收到的消息的名称(字符串)</param>
        /// <param name="_ReturnStrName">返回的消息的名称(字符串)</param>
        public NetWorkTcpServer(string _ReceiveObjName = "", string _ReturnObjName = "", string _ReceiveStrName = "", string _ReturnStrName = "")
        {
            ReceiveObjName = _ReceiveObjName;
            ReturnObjName = _ReturnObjName;
            ReceiveStrName = _ReceiveStrName;
            ReturnStrName = _ReturnStrName;
            NetworkComms.AppendGlobalConnectionCloseHandler(connectionShutdownHandle);
            NetworkComms.AppendGlobalConnectionEstablishHandler(connectionEstablishHandle);
        }

        /// <summary>
        /// 初始化监听类库
        /// </summary>
        /// <param name="_ReceiveObjName">收到的消息的名称(对象)</param>
        public NetWorkTcpServer(string _ReceiveObjName)
        {
            ReceiveObjName = _ReceiveObjName;
            NetworkComms.AppendGlobalConnectionCloseHandler(connectionShutdownHandle);
            NetworkComms.AppendGlobalConnectionEstablishHandler(connectionEstablishHandle);
        }

        /// <summary>
        /// 开始监听
        /// </summary>
        /// <param name="ServerAddress"></param>
        public void StartListening(string ServerAddress)
        {
            string[] ServerAddress_Arr = ServerAddress.Split(':');
            SendReceiveOptions sro = new SendReceiveOptions(DPSManager.GetDataSerializer<ProtobufSerializer>(), null, null);//指定序列化方式
            listener = new TCPConnectionListener(sro, ApplicationLayerProtocolStatus.Enabled);//启动应用层
            IPEndPoint thePoint = new IPEndPoint(IPAddress.Parse(ServerAddress_Arr[0]), Convert.ToInt32(ServerAddress_Arr[1]));
            NetworkComms.DisableLogging();//关闭日志
            Connection.StartListening(listener, thePoint);//创建监听
        }

        /// <summary>
        /// 停止监听
        /// </summary>
        /// <param name="_IP"></param>
        /// <param name="_Port"></param>
        public void StopServerListening()
        {
            NetworkComms.CloseAllConnections();//断开所有连接
            Connection.StopListening(listener);//停止监听
        }

        /// <summary>
        /// 给指定连接发送消息
        /// </summary>
        /// <typeparam name="X">消息类型</typeparam>
        /// <param name="_Data">发送 数据</param>
        /// <param name="connnectionInfos">连接列表</param>
        /// <returns></returns>
        public bool SendAssignData<X>(X _Data, List<ConnectionInfo> connnectionInfos)
        {
            try
            {
                //List<ConnectionInfo> connnectionInfos = NetworkComms.AllConnectionInfo();//获取所有连接
                foreach (ConnectionInfo _connectionInfo in connnectionInfos)//排除掉板卡连接来转发
                {
                    Connection _connection = NetworkComms.GetExistingConnection(_connectionInfo);
                    _connection.SendObject("ServerToData", _Data);
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 上线事件
        /// </summary>
        /// <param name="connection"></param>
        private void connectionEstablishHandle(Connection connection)
        {
            ConnOnlineCount++;
            if (!string.IsNullOrEmpty(ReceiveObjName))
            {
                connection.AppendIncomingPacketHandler<XYZ>(ReceiveObjName, ReceivepacketObjHandler);
            }
            if (!string.IsNullOrEmpty(ReturnObjName))
            {
                connection.AppendIncomingPacketHandler<XYZ>(ReturnObjName, ReturpacketObjHandler);
            }
            if (!string.IsNullOrEmpty(ReceiveStrName))
            {
                connection.AppendIncomingPacketHandler<string>(ReceiveStrName, ReceivepacketStrHandler);
            }
            if (!string.IsNullOrEmpty(ReturnStrName))
            {
                connection.AppendIncomingPacketHandler<string>(ReturnStrName, ReturpacketStrHandler);
            }
            EventOnLine?.Invoke(connection.ConnectionInfo);
        }

        /// <summary>
        /// 下线事件
        /// </summary>
        /// <param name="connection"></param>
        private void connectionShutdownHandle(Connection connection)
        {
            ConnOnlineCount--;
            EventOffLine?.Invoke(connection.ConnectionInfo);
        }

        /// <summary>
        /// 获取所有连接对象
        /// </summary>
        /// <returns></returns>
        public List<Connection> GetConnections()
        {
            List<Connection> connections = new List<Connection>();
            List<ConnectionInfo> connectionInfos = NetworkComms.AllConnectionInfo();
            foreach (ConnectionInfo item in connectionInfos)
            {
                connections.Add(TCPConnection.GetConnection(item));
            }
            return connections;
        }

        /// <summary>
        ///服务端接收消息处理方法(对象)
        /// </summary>
        /// <param name="packetHeader"></param>
        /// <param name="connection"></param>
        /// <param name="incomingObject"></param>
        private void ReceivepacketObjHandler(PacketHeader packetHeader, Connection connection, XYZ incomingObject)
        {
            MessgeObjHandle?.Invoke(connection, incomingObject);
        }

        /// <summary>
        ///需要返回的消息处理事件(对象)
        /// </summary>
        /// <param name="packetHeader"></param>
        /// <param name="connection"></param>
        /// <param name="incomingObject"></param>
        private void ReturpacketObjHandler(PacketHeader packetHeader, Connection connection, XYZ incomingObject)
        {
            ReturnMessgeObjHandle?.Invoke(connection, incomingObject);
        }

        /// <summary>
        /// 服务端接收消息处理方法(字符串)
        /// </summary>
        /// <param name="packetHeader"></param>
        /// <param name="connection"></param>
        /// <param name="incomingObject"></param>
        private void ReceivepacketStrHandler(PacketHeader packetHeader, Connection connection, string incomingObject)
        {
            MessgeStrHandle?.Invoke(connection, incomingObject);
        }

        /// <summary>
        /// 需要返回的消息处理事件（字符串）
        /// </summary>
        /// <param name="packetHeader"></param>
        /// <param name="connection"></param>
        /// <param name="incomingObject"></param>
        private void ReturpacketStrHandler(PacketHeader packetHeader, Connection connection, string incomingObject)
        {
            ReturnMessgeStrHandle?.Invoke(connection, incomingObject);
        }
    }

    #endregion 托管服务端
}